﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace Utils
{
    public class ExpandQuerry
    {


        Dictionary<string, string> dict = new Dictionary<string, string>();

        int range;
        private int p;

       

        public ExpandQuerry(int p)
        {
            readThresures();
            this.range = p;
            
        }

       

        private void readThresures()
        {
            var reader = new StreamReader(File.OpenRead(@"mthesaur.txt"));
            dict = new Dictionary<string, string>();
            while (!reader.EndOfStream)
            {

                string line = reader.ReadLine();
                if (line == null) continue;

                string[] splitLine = line.Split(',');

                string mainWord = splitLine[0];
                line = line.Replace(mainWord + ",", string.Empty);
                try
                {
                    if (!dict.ContainsKey(mainWord))
                    {

                        dict.Add(mainWord, line);
                    }
                }
                catch (ArgumentException argEx)
                {
                    Console.WriteLine("Attempted to add {0} to the dictionary but it already exists.", mainWord);
                }
            }

        }

        public List<string> findThresures(string querry)
        {

            string[] splitLine = querry.Split(' ');
            string newQuerry = "";
            if (dict.ContainsKey(querry))
            {
                newQuerry = dict[querry];
            }

            if (dict.ContainsKey(querry.Replace(" ", string.Empty)))
            {
                newQuerry = dict[querry.Replace(" ", string.Empty)];
            }

            if (dict.ContainsKey(splitLine[splitLine.Length - 1]))
            {
                newQuerry = dict[splitLine[splitLine.Length - 1]];
            }

     
                return chooseThresures(querry, newQuerry);

        }

        public List<string> chooseThresures(string querry, string words)
        {
            
            Dictionary<string, int> LevenDist = new Dictionary<string, int>();
            List<string> resultList = new List<string>();

            if (words != "")
            {
                string[] splitLine = words.Split(',');
                for (int i = 0; i < splitLine.Length; i++)
                {
                    //LevenDist.Add(splitLine[i], LevenshteinDistance(splitLine[i], splitLine[i].Length, querry, querry.Length));
                    LevenDist.Add(splitLine[i], Compute(splitLine[i], querry));
                        
                }

                List<KeyValuePair<string, int>> myList = LevenDist.ToList();
                myList.Sort((firstPair, nextPair) =>
                {
                    return firstPair.Value.CompareTo(nextPair.Value);
                }
                );

                for (int i = 0; i < range; i++)
                {
                    KeyValuePair<string, int> tmp = myList[i];
                    resultList.Add(tmp.Key);
                }
            }
            return resultList;

        }

    public  int Compute(string s, string t)
    {
	    int n = s.Length;
	    int m = t.Length;
	    int[,] d = new int[n + 1, m + 1];

	    // Step 1
	    if (n == 0)
	    {
	        return m;
	    }

	    if (m == 0)
	    {
	        return n;
	    }

	    // Step 2
	    for (int i = 0; i <= n; d[i, 0] = i++)
	    {
	    }

	    for (int j = 0; j <= m; d[0, j] = j++)
	    {
	    }

	    // Step 3
	    for (int i = 1; i <= n; i++)
	    {
	        //Step 4
	        for (int j = 1; j <= m; j++)
	        {
		    // Step 5
		    int cost = (t[j - 1] == s[i - 1]) ? 0 : 1;

		    // Step 6
		    d[i, j] = Math.Min(
		        Math.Min(d[i - 1, j] + 1, d[i, j - 1] + 1),
		        d[i - 1, j - 1] + cost);
	        }
	    }
	    // Step 7
	    return d[n, m];
    }




        private int LevenshteinDistance(string s, int len_s, string t, int len_t)
        {
            int cost;
            if (len_s == 0) return len_t;
            if (len_t == 0) return len_s;

            if (s[len_s - 1] == t[len_t - 1])
                cost = 0;
            else
                cost = 1;
            return Math.Min(LevenshteinDistance(s, len_s - 1, t, len_t) + 1,
                           Math.Min(LevenshteinDistance(s, len_s, t, len_t - 1) + 1,
                           LevenshteinDistance(s, len_s - 1, t, len_t - 1) + cost));
        }





    }
}
